#include "MeshFactory.h"
#include "MathUtils.h"

void buildOctahedron(VEC4ARRAY& vec4Vertex) 
{
	// triangle 1
	VECTOR_4 a = { 1, 0, 1,		1};
	VECTOR_4 b = { 1, 0,-1,		1};
	VECTOR_4 c = { 0, 1, 0,		1};
	addTriangle(vec4Vertex, a, b, c);
	// triangle 2
	VECTOR_4 d = { 1, 0,-1,		1};
	VECTOR_4 e = {-1, 0,-1,		1};
	VECTOR_4 f = { 0, 1, 0,		1};
	addTriangle(vec4Vertex, d, e, f);
	// triangle 3 = triangle 1 (-x)
	a.x = -1; b.x = -1;
	addTriangle(vec4Vertex, b, a, c);
	// triangle 4 = triangle 2 (-z)
	d.z = -1; e.z = -1;
	addTriangle(vec4Vertex, e, d, f);
}

void subDivide(VEC4ARRAY& vec4Vertex, UINT32 iSubdivisionMult) 
{
	VEC4ARRAY tempVertexArray;
	for (UINT32 i=0; i<iSubdivisionMult; i++)
	{		
		tempVertexArray.clear();
		tempVertexArray.reserve(4*vec4Vertex.size());
		for (UINT32 j=0; j<vec4Vertex.size(); j+=3)
		{
			VECTOR_4& a = vec4Vertex[j+0];
			VECTOR_4& b = vec4Vertex[j+1];
			VECTOR_4& c = vec4Vertex[j+2];
			VECTOR_4 a_b = ((a + b) * 0.5f).normalize();
			VECTOR_4 b_c = ((b + c) * 0.5f).normalize();
			VECTOR_4 c_a = ((c + a) * 0.5f).normalize();
			addTriangle(tempVertexArray,   a, a_b, c_a);
			addTriangle(tempVertexArray, a_b,   b, b_c);
			addTriangle(tempVertexArray, a_b, b_c, c_a);
			addTriangle(tempVertexArray, c_a, b_c,   c);
		}
		vec4Vertex = std::move(tempVertexArray);
	}
}



void buildSphereFromOctahedron(Mesh3d& mshDest, UINT32 iSubdivisionMult)
{
	VEC4ARRAY vec4Vertex;
	const UINT32 iOctahedronVertexCount = 3*8;
	vec4Vertex.reserve(iOctahedronVertexCount);
	buildOctahedron(vec4Vertex);
	subDivide(vec4Vertex, iSubdivisionMult);
	mshDest.setVertexArray(vec4Vertex);
}

void MeshFactory::buildSphere(Mesh3d& mshDest, MeshFactory::ESphereBuild mode, UINT32 iSubdivisionMult)
{
	switch (mode)
	{
	case FROM_TETRAHEDRON:
		throw "SPHERE MODE NOT IMPLEMENTED";
		std::clog << "Building a sphere mesh using tetrahedron with "<< iSubdivisionMult << " subdivisions..."<< std::endl;
		break;
	case FROM_OCTAHEDRON:
		std::clog << "Building a sphere mesh using octahedron with "<< iSubdivisionMult << " subdivisions..."<< std::endl;
		buildSphereFromOctahedron(mshDest, iSubdivisionMult);
		break;
	case FROM_ICOSAHEDRON:
		std::clog << "Building a sphere mesh using icosahedron with "<< iSubdivisionMult << " subdivisions..."<< std::endl;
		throw "SPHERE MODE NOT IMPLEMENTED";
		break;
	}
	std::clog << "Built sphere with "<< mshDest.getVertexArray().size() << " vertices" << std::endl;
}